home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / PC_TNC2.C < prev    next >
C/C++ Source or Header  |  1990-05-03  |  11KB  |  382 lines

  1. /* Support routines for TNC2 emulator - PC version */
  2.  
  3. #include "global.h"
  4. #include "asy.h"
  5. #include "ax25.h"
  6. #include "timer.h"
  7. #include "slip.h"
  8. #include "tnc2.h"
  9.  
  10. #define     PIPEBUF    512            /* size of a pipe buffer */
  11. #define     FLOW_LOW    64            /* low-water mark */
  12. #define     FLOW_HIGH    480            /* high-water mark */
  13.  
  14. /* INT14 vector stored at a second location for use under DoubleDOS */
  15. /* This location is at the end of the "intra-application comm area" */
  16. static void (*far *int14vec)() = (void (*far *)()) 0x000004fcL;
  17.  
  18. static char tnc2installed = 0;            /* vector already set? */
  19. extern void (*far tnc2ovec)();            /* location to store old int14 vec */
  20. extern char nospace[];
  21.  
  22. /* routine that simulates a character device to the client */
  23. /* this one is called from an INT14 replacement, in the context */
  24. /* of the client!  so don't call to many other routines, and don't */
  25. /* try to create pointers to variables in the stack!! (SS != DS) */
  26. /* the parameters are the registers pushed by the assembly language */
  27. /* routine, and it will pop them back on return. if returnval=0, it will */
  28. /* jump to the original handler (to handle other ports) */
  29. /* entry conditions: AH=function code  AL=char or param     DX=port (from 0) */
  30. /* exit conditions: AX=return value  HDL=handler code */
  31. int
  32. int14(di,dx,cx,bx,ax,ds,es)
  33. unsigned short di,dx,cx,bx,ax,ds,es;
  34. {
  35.     register struct tnc *tnc2;
  36.     int i;
  37.  
  38.     for (tnc2 = tnc2s; tnc2 != NULLTNC; tnc2 = tnc2->next)
  39.     if (tnc2->dev == dx + 1)        /* this one handled by us? */
  40.          break;
  41.  
  42.     if (tnc2 == NULLTNC)            /* when not found... */
  43.     return 0;                /* let someone else deal with it */
  44.  
  45.     switch (ax >> 8)                /* switch on function code */
  46.     {
  47.     case 1:                    /* Send character */
  48.     i = 250;
  49.  
  50.     while (((!(tnc2->status & TS_TXBUF) &&    /* not allowed to buffer? */
  51.          tnc2->input.num != 0) ||    /* already something there */
  52.         tnc2->input.num == PIPEBUF) &&    /* buffer full? */
  53.            --i)                /* not the max tries? */
  54.         giveup();                /* give NET a chance to read */
  55.  
  56.     if (tnc2->input.num == PIPEBUF) {    /* (still) full? */
  57.         tnc2->status |= TS_RXOVR;        /* then we have an overrun */
  58.         ax = 0x8000 | (ax & 0xff);        /* 'timeout' error + char */
  59.         goto rxstatus;            /* plus the receiver status */
  60.     }
  61.  
  62.     *tnc2->input.in++ = uchar(ax);        /* save the character */
  63.     if (tnc2->input.in == tnc2->input.end)
  64.         tnc2->input.in = tnc2->input.begin;
  65.     if (++(tnc2->input.num) >= FLOW_HIGH)
  66.         tnc2->status |= TS_RXSTOP;
  67.  
  68.     /* finally, return the status in AH and sent char in AL */
  69.  
  70.     ax &= 0xff;                /* keep only char */
  71.     goto trxstatus;
  72.  
  73.     case 2:                    /* Receive character */
  74.     i = 50;
  75.  
  76.     while (tnc2->output.num == 0 && --i)    /* no char(s) in buffer? */
  77.         giveup();
  78.  
  79.     if (tnc2->output.num == 0){        /* still nothing? */
  80.         ax = 0x8048 | (tnc2->status & TS_DCD); /* 'timeout' error */
  81.         goto trxstatus;
  82.     }
  83.  
  84.     ax = uchar(*tnc2->output.out++);    /* AL is received char */
  85.     if (tnc2->output.out == tnc2->output.end)
  86.         tnc2->output.out = tnc2->output.begin;
  87.     if (--(tnc2->output.num) < FLOW_LOW)
  88.         tnc2->status &= ~TS_TXSTOP;
  89.  
  90.     goto trxstatus;                /* add tx & rx status in AH */
  91.  
  92.     case 0:                    /* Initialize */
  93.     /* flush the input and output buffers */
  94.     tnc2->input.in = tnc2->input.out = tnc2->input.begin;
  95.     tnc2->input.num = 0;
  96.     tnc2->output.in = tnc2->output.out = tnc2->output.begin;
  97.     tnc2->output.num = 0;
  98.  
  99.     /* keep only the DCD and TXBUF bits in the status (rest is volatile) */
  100.     tnc2->status &= TS_DCD | TS_TXBUF;
  101.                         /* return status like: */
  102.     case 3:                    /* Status request */
  103. allstatus:
  104.     if (tnc2->input.num != 0 &&        /* something in buffer? */
  105.         !(tnc2->status & TS_TXBUF))        /* not allowed to buffer? */
  106.         giveup();                /* let NET read the char now */
  107.  
  108.     ax = 0x0048 | (tnc2->status & TS_DCD);    /* default status = DSR DDCD */
  109.  
  110.     if (tnc2->input.num < FLOW_LOW ||    /* below flow control treshold? */
  111.         (!(tnc2->status & TS_RXSTOP) && tnc2->input.num < FLOW_HIGH))
  112.         ax |= 0x10;                /* turn on CTS */
  113.  
  114. trxstatus:
  115.     if (tnc2->input.num == 0)        /* buffer empty? */
  116.         ax |= 0x6000;            /* then turn on TEMT and THRE */
  117.  
  118.     if ((tnc2->status & TS_TXBUF) &&    /* allowed to buffer? */
  119.         tnc2->input.num < PIPEBUF)        /* buffer not yet full? */
  120.         ax |= 0x2000;            /* then turn on THRE */
  121.  
  122. rxstatus:
  123.     if (tnc2->output.num != 0)        /* char(s) in buffer? */
  124.         ax |= 0x0100;            /* turn on data ready */
  125.  
  126.     if (tnc2->status & TS_TXOVR) {        /* transmitter overrun? */
  127.         tnc2->status &= ~TS_TXOVR;
  128.         ax |= 0x0200;            /* turn on overrun error */
  129.     }
  130.  
  131.     break;
  132.  
  133.     case 4:                    /* Inquiry */
  134.     ax = 0xaa55;                /* Return AA55 to caller */
  135.     break;
  136.  
  137.     case 5:                    /* Drop DTR & RTS (MBBIOS) */
  138.     tnc2->status |= TS_TXHOLD;
  139.     goto allstatus;
  140.  
  141.     case 6:                    /* Raise DTR & RTS (MBBIOS) */
  142.     tnc2->status &= ~TS_TXHOLD;
  143.     goto allstatus;
  144.  
  145.     case 7:                    /* Send Break (MBBIOS) */
  146.     i = 150;                /* First allow buffer to drain */
  147.  
  148.     while (tnc2->output.num != 0 && --i)    /* char(s) in buffer? */
  149.         giveup();
  150.  
  151.     tnc2->status |= TS_BREAK;        /* set the "BREAK Received" flag */
  152.     goto allstatus;
  153.  
  154.     case 8:                    /* Non-destr Read (MBBIOS) */
  155.     ax = uchar(*tnc2->output.out);        /* AL is next char */
  156.     goto trxstatus;                /* add tx & rx status in AH */
  157.  
  158.     case 9:                    /* Set/Get Options (MBBIOS 3.2) */
  159.     if (ax & TS_TXBUF) {            /* Only support TX Buf switching */
  160.         ax = 0x44 | (tnc2->status & TS_TXBUF); /* Highspeed/HW Handshake/TX Buffering */
  161.         tnc2->status |= TS_TXBUF;
  162.     } else {
  163.         ax = 0x44 | (tnc2->status & TS_TXBUF); /* Highspeed/HW Handshake/TX Buffering */
  164.         tnc2->status &= ~TS_TXBUF;
  165.     }
  166.     break;
  167.  
  168.     case 10:                    /* Write Buffer (MBBIOS 3.2) */
  169.     while (cx != 0 &&            /* more to go? */
  170.            tnc2->input.num != PIPEBUF) {    /* buffer not full? */
  171.         *tnc2->input.in++ = ((char far *) ((long) es << 16))[di++];
  172.         if (tnc2->input.in == tnc2->input.end)
  173.         tnc2->input.in = tnc2->input.begin;
  174.         if (++(tnc2->input.num) >= FLOW_HIGH)
  175.         tnc2->status |= TS_RXSTOP;
  176.         cx--;
  177.     }
  178.  
  179.     goto allstatus;
  180.  
  181.     case 11:                    /* Read Buffer (MBBIOS 3.2) */
  182.     i = cx;                    /* move bytecount to temp */
  183.     cx = 0;                    /* number of bytes done */
  184.  
  185.     while (i-- && tnc2->output.num != 0) {    /* more requested & more available */
  186.         ((char far *) ((long) es << 16))[di++] = *tnc2->output.out++;
  187.         if (tnc2->output.out == tnc2->output.end)
  188.         tnc2->output.out = tnc2->output.begin;
  189.         if (--(tnc2->output.num) < FLOW_LOW)
  190.         tnc2->status &= ~TS_TXSTOP;
  191.         cx++;
  192.     }
  193.  
  194.     goto allstatus;
  195.  
  196.     default:                    /* Unrecognized request */
  197.     ax = 0;                    /* Let's just return 0 */
  198.     break;
  199.     }
  200.  
  201.     return 1;                    /* we've handled it! */
  202. }
  203.  
  204. /* public routines for use by tnc2 emulator */
  205. /* initialize TNC2 client port */
  206. int
  207. tnc2_init (tnc2)
  208. register struct tnc *tnc2;
  209.  
  210. {
  211.     extern void tnc2vec();
  212. #ifndef __TURBOC__
  213.     void (*getvect())();
  214. #endif
  215. #ifdef COMBIOS
  216.     unsigned int dev = tnc2->dev - 1;        /* BIOS-compat dev */
  217. #endif
  218.  
  219.     tnc2->status = 0;                /* Unbuffered, all OFF */
  220.  
  221. #ifdef COMBIOS
  222.     /* check if it is a BIOS-supported port, and assume external port if so */
  223.  
  224.     if (dev < ASY_MAX && combios(0x00e3,dev) != 0x00e3){
  225.     if (com_init(dev) || com_speed(dev,9600,"h"))
  226.         return 1;
  227.  
  228.     return 0;
  229.     }
  230. #endif
  231.  
  232.     if ((tnc2->input.begin = malloc(PIPEBUF)) == NULLCHAR){
  233.     printf(nospace);
  234.     return 1;
  235.     }
  236.     tnc2->input.in = tnc2->input.out = tnc2->input.begin;
  237.     tnc2->input.end = tnc2->input.begin + PIPEBUF;
  238.     tnc2->input.num = 0;
  239.  
  240.     if ((tnc2->output.begin = malloc(PIPEBUF)) == NULLCHAR){
  241.     free(tnc2->input.begin);
  242.     printf(nospace);
  243.     return 1;
  244.     }
  245.     tnc2->output.in = tnc2->output.out = tnc2->output.begin;
  246.     tnc2->output.end = tnc2->output.begin + PIPEBUF;
  247.     tnc2->output.num = 0;
  248.  
  249.     if (!tnc2installed) {            /* not yet installed? */
  250.     tnc2ovec = getvect(0x14);        /* save existing vector */
  251.     setvect(0x14,tnc2vec);            /* install our handler */
  252.     *int14vec = tnc2vec;            /* save a second time */
  253.     tnc2installed = 1;
  254.     }
  255.  
  256.     return 0;
  257. }
  258.  
  259. /* terminate TNC2 client port */
  260. void
  261. tnc2_term